async awaitで何かを待つような処理を同期的に書く
async awaitで何かを待つような処理を同期的に書く
mouse down, move up といったイベントドリブンな処理に基づいて、「canvas内でお絵かき」みたいなしょりを書きたいとする
そういうのを、「マウスをdownして、move(ドラッグ)して、mouseがupするのをまつ」という流れをそのまま同期的に記述できると嬉しい。
code:js
while(true) {
const event = await mouseDownPromise()
const downPos = {x: event.clinetX, y: event.clientY }
const onMove = () => {/* drag中の処理 downPosも参照できる */}
window.addEventListener('mousemove', onMove)
const upEvent = await mouseUpPromise()
window.removeEventListener('mousemove', onMove) // mouseupがresolveされたらmoveを終了
// mouseup時の処理
}
ちょい改善
これは、down -> move -> up の繰り返しを書いたもの
Promiseを得るのは引数経由で注入するといいだろう
moveする前にupする場合を考えるとraceする必要がある
code:ts
type Hook = (
waitFor: (key: keyof SVGSVGElementEventMap) => Promise<PointerEvent>
) => void;
const hook: Hook = async (waitFor) => {
while (true) {
const down = await waitFor("pointerdown");
console.log(down);
async function loopUntilUp() {
while (true) {
const e = await Promise.race([
waitFor("pointerup"),
waitFor("pointermove"),
]);
if (e.type === "pointerup") {
return e;
}
console.log(e.clientX, e.clientY);
}
}
const up = await loopUntilUp();
console.log(up);
}
};
メリット
サイクルがwhile ループで表現できてる
何らかの数字を保持したいなら、ただ単に変数として保持すればよい
mousedown時のデータは、moveやupのときに、単なる外側スコープの変数として参照できる
mousedown時のeventをawaitしたおかげ
mousedown, move, upのcallback内で外側の変数にデータを保持して、moveやup時にそれを参照するのはmutableで、頭がパンクする
stateとeffectが散り散りにならない
細かい仕様変更がやりやすくなると思う
デメリット
書いてる最中にミスると無限ループが発生してパソコンが熱くなる
whileの宿命
moveとかを毎度promise生成して待ち受けるのがパフォーマンス的に悪いとかあるかなあ?
この書き方はmiyamonz.iconはここから知った
モーダルをまつ
キューを保持して一個ずつ消化する
ユーザの反応で消す
「ユーザがモーダルを消すまで」をpromiseとして抽象化する